package com.chezhujie.www.core;

import com.chezhujie.www.utils.LocalDateTime;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.mapping.SqlSource;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;

@Component
@Intercepts({@Signature(type=Executor.class,method="query",args={ MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class })})
public class PageInterceptor implements Interceptor {

	private static final Logger log = LoggerFactory.getLogger(PageInterceptor.class);




    public Object intercept(Invocation invocation) throws Throwable {
	//http://duanhengbin.iteye.com/blog/1998017
    //当前环境 MappedStatement，BoundSql，及sql取得
   /* MappedStatement mappedStatement=(MappedStatement)invocation.getArgs()[0];    
    Object parameter = invocation.getArgs()[1]; 
    BoundSql boundSql = mappedStatement.getBoundSql(parameter); 
    String originalSql = boundSql.getSql().trim();
    Object parameterObject = boundSql.getParameterObject();

    //Page对象获取，“信使”到达拦截器！
//    Page page = searchPageWithXpath(boundSql.getParameterObject(),".","page","page");

//    if(page!=null ){
      //Page对象存在的场合，开始分页处理
      String countSql = getCountSql(originalSql);
      Connection connection=mappedStatement.getConfiguration().getEnvironment().getDataSource().getConnection()  ;          
      PreparedStatement countStmt = connection.prepareStatement(countSql);  
      BoundSql countBS = copyFromBoundSql(mappedStatement, boundSql, countSql);
      DefaultParameterHandler parameterHandler = new DefaultParameterHandler(mappedStatement, parameterObject, countBS);
      parameterHandler.setParameters(countStmt);
      ResultSet rs = countStmt.executeQuery();
      int totpage=0;
      if (rs.next()) {  
        totpage = rs.getInt(1);  
      }
      rs.close();  
      countStmt.close();  
      connection.close();
      
      //分页计算
//      page.setTotalRecord(totpage);
      
      //对原始Sql追加limit
//      int offset = (page.getPageNo() - 1) * page.getPageSize();
      StringBuffer sb = new StringBuffer();
//      sb.append(originalSql).append(" limit ").append(offset).append(",").append(page.getPageSize());
      BoundSql newBoundSql = copyFromBoundSql(mappedStatement, boundSql, sb.toString());
      MappedStatement newMs = copyFromMappedStatement(mappedStatement,new BoundSqlSqlSource(newBoundSql));  
      invocation.getArgs()[0]= newMs;  
//    }
    return invocation.proceed();*/
        if (PropertiesData.getProperties("showSql")!=null&&"TRUE".equals(PropertiesData.getProperties("showSql").toUpperCase())) {
            try {

                    MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
                    Object parameter = invocation.getArgs()[1];
                    BoundSql boundSql = mappedStatement.getBoundSql(parameter);
                    String originalSql = boundSql.getSql().trim();
                    Object parameterObject = boundSql.getParameterObject();

                    if (parameterObject instanceof Map) {

                        @SuppressWarnings("unchecked")
                        Map<String, Object> object = (Map<String, Object>) parameterObject;
                        List<Object> listObj = new ArrayList<Object>();

                        for (Entry<String, Object> mp : object.entrySet()) {
                            if (mp.getValue() instanceof List) {
                                listObj = (List<Object>) mp.getValue();
                            }
                        }
                        String item = "";
                        int h = 0;
                        for (ParameterMapping mapping : boundSql.getParameterMappings()) {
                            String[] strings = mapping.getProperty().split("\\.");
                            if (strings.length == 1) {
                                if (object.get(mapping.getProperty()) == null) {
                                    if (listObj.size() == 0) {
                                        originalSql = originalSql.replaceFirst("[?]", "''");
                                    } else {
                                        originalSql = originalSql.replaceFirst("[?]", "'" + listObj.get(h) + "'");
                                    }
                                    h++;
                                } else {
                                    originalSql = originalSql.replaceFirst("[?]", "'" + object.get(mapping.getProperty()) + "'");
                                }

                            } else if (strings.length == 2) {
                                if (!item.equals(strings[0])) {
                                    item = strings[0];
                                    h++;
                                }
                                originalSql = originalSql.replaceFirst("[?]", "'" + ((Map<String, Object>) listObj.get(h - 1)).get(strings[1]) + "'");
                            }
                        }


                    } else if (parameterObject instanceof String) {
                        String str = (String) parameterObject;
                        originalSql = originalSql.replaceFirst("[?]", "'" + str + "'");
                    }

                    System.out.println(mappedStatement.getResource());
                    System.out.println(mappedStatement.getId());
                    System.out.println("==============================sql开始============================" + LocalDateTime.now());
                    System.out.println(deleteCRLFOnce(originalSql));
                    System.out.println("==============================sql结束============================" + LocalDateTime.now());
                    if (parameterObject != null) {
                        System.out.println(parameterObject.toString());
                    }
                } catch(Exception e){
                    System.err.println("显示sql出错！");
                    //			e.printStackTrace();
                }
            }
        return invocation.proceed();
	}
  
 

  /**
   * 复制MappedStatement对象
   */
 /* private MappedStatement copyFromMappedStatement(MappedStatement ms, SqlSource newSqlSource) {
    Builder builder = new Builder(ms.getConfiguration(),ms.getId(),newSqlSource,ms.getSqlCommandType());
    
    builder.resource(ms.getResource());
    builder.fetchSize(ms.getFetchSize());
    builder.statementType(ms.getStatementType());
    builder.keyGenerator(ms.getKeyGenerator());
    builder.keyProperty(ms.getKeyProperty());
    builder.timeout(ms.getTimeout());
    builder.parameterMap(ms.getParameterMap());
    builder.resultMaps(ms.getResultMaps());
    builder.resultSetType(ms.getResultSetType());
    builder.cache(ms.getCache());
    builder.flushCacheRequired(ms.isFlushCacheRequired());
    builder.useCache(ms.isUseCache());
    
    return builder.build();
  }*/

  /**
   * 复制BoundSql对象
   */
 /* private BoundSql copyFromBoundSql(MappedStatement ms, BoundSql boundSql, String sql) {
    BoundSql newBoundSql = new BoundSql(ms.getConfiguration(),sql, boundSql.getParameterMappings(), boundSql.getParameterObject());
    for (ParameterMapping mapping : boundSql.getParameterMappings()) {
        String prop = mapping.getProperty();
        if (boundSql.hasAdditionalParameter(prop)) {
            newBoundSql.setAdditionalParameter(prop, boundSql.getAdditionalParameter(prop));
        }
    }
    return newBoundSql;
  }*/

  /**
   * 根据原Sql语句获取对应的查询总记录数的Sql语句
   */
  private String getCountSql(String sql) {
    return "SELECT COUNT(*) FROM (" + sql + ") aliasForPage";
  }

  public class BoundSqlSqlSource implements SqlSource {
      BoundSql boundSql;
      public BoundSqlSqlSource(BoundSql boundSql) {
        this.boundSql = boundSql;  
      }  
      public BoundSql getBoundSql(Object parameterObject) {
        return boundSql;  
      }  
    }  
  public Object plugin(Object arg0) {
     return Plugin.wrap(arg0, this);
  }
  public void setProperties(Properties arg0) {
  }
  private static String deleteCRLFOnce(String input) {
	    return input.replaceAll("((\r\n)|\n)[\\s\t ]*(\\1)+", "$1");  
  }  
}